#pragma once

// #include <glad/glad.h>

#include <array>
#include <shared_mutex>
#include <vector>

#define QT_NO_SIGNALS_SLOTS_KEYWORDS
#define QT_NO_EMIT

#include <QObject>
#include <QOpenGLFunctions_4_5_Core>
#include <QSize>

#include <glm/glm.hpp>

#include <algorithm/analytical_model/RectangleGrid.h>
#include <algorithm/analytical_model/algorithm/cuda/inter_op/Data.h>
#include <algorithm/shared/data/topology/geometry/Geometry.h>
#include <utils/Concepts.h>
#include <utils/HasValue.h>
#include <utils/Math.h>

// #include <boost/ptr_container/ptr_vector.hpp>

QT_BEGIN_NAMESPACE
class QQuickWindow;
class QOpenGLShaderProgram;
class QOpenGLTexture;
class QOpenGLBuffer;
QT_END_NAMESPACE

namespace solar
{
    struct AnalyticalPipelineParam;

    class SceneRenderer : public QObject, protected QOpenGLFunctions_4_5_Core
    {
            Q_OBJECT
        public:
            SceneRenderer();
            ~SceneRenderer() override;
            Q_DISABLE_COPY_MOVE(SceneRenderer)

            void setViewportSize(const QSize& size);
            void setWindow(QQuickWindow* window);
            void updateScene(FUNC_CONST_INPUT AnalyticalPipelineParam* params);
            void updateSceneForSunray();
            void setFocusCenter(const solar::cuda::inter_op::Float3& focus_center);
            void setSunrayDirection(const solar::cuda::inter_op::Float3& sunray_dir);
            void rotateLookAtCenterHorizontal(float degree);
            void rotateLookAtCenterVertical(float degree);
            void rotateLookAtCenter(float horizontal_degree, float vertical_degree);
            void moveCameraCenter(float delta_x, float delta_y, float delta_z);
            void moveLookAtCenter(float delta_x, float delta_y, float delta_z);

        public Q_SLOTS:
            void init();
            void paint();

        private:
            QSize viewport_size_;
            QOpenGLShaderProgram* program_;
            QOpenGLShaderProgram* program_with_texture_;
            QOpenGLShaderProgram* program_skybox_;
            QOpenGLShaderProgram* program_skybox_reflect_upper_face_;
            QQuickWindow* window_;

            // Unused, may be removed in the future
            glm::vec4 light_position_ = {0, 180, 0, 0};
            glm::vec4 light_ambient_ = {0.3F, 0.3F, 0.3F, 1};
            glm::vec4 light_diffuse_ = {1, 1, 1, 1};
            glm::vec4 light_specular_ = {1, 1, 1, 1};
            glm::vec3 light_direction_ = {0.306454, -0.790155, 0.530793};
            glm::vec3 eye_ = {173.177, 6, -339.971};
            glm::vec3 center_ = {163.177, 3, -349.971};
            std::shared_mutex update_data_mutex_;
            solar::cuda::inter_op::Float3 focus_center_{0, 180, 0};
            solar::cuda::inter_op::Float3 sunray_dir_{0.306454, -0.790155, 0.530793};
            solar::analytical::RectangleGrid rectangle_grid_;
            bool scene_updated_ = false;
            bool scene_updated_for_sunray_ = false;

            class Vertex
            {
                public:
                    float position_[3];
                    float normal_[3];
                    float coord_[2];
                    float color_[4];
                    static constexpr auto position_size_ = 3;
                    static constexpr auto normal_size_ = 3;
                    static constexpr auto coord_size_ = 2;
                    static constexpr auto color_size_ = 4;
            };

            static constexpr std::array rectangle_indices_ = {0U, 1U, 2U, 0U, 2U, 3U};

            static constexpr std::array square_vertices_ = {
                Vertex{{-0.5, -0.5, 0}, {0, 0, 1}, {0, 0}, {0, 1, 0, 1}},
                Vertex{ {0.5, -0.5, 0}, {0, 0, 1}, {1, 0}, {0, 1, 0, 1}},
                Vertex{  {0.5, 0.5, 0}, {0, 0, 1}, {1, 1}, {0, 1, 0, 1}},
                Vertex{ {-0.5, 0.5, 0}, {0, 0, 1}, {0, 1}, {0, 1, 0, 1}}
            };

            static constexpr std::array ground_vertices_ = {
                Vertex{
                       {-0.5, 0, -0.5}, {0, 1, 0}, {0, 0}, {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}},
                Vertex{
                       {0.5, 0, -0.5}, {0, 1, 0}, {1, 0}, {217 / 255.0, 217 / 255.0, 204 / 255.0, 1} },
                Vertex{
                       {0.5, 0, 0.5}, {0, 1, 0}, {1, 1}, {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}  },
                Vertex{
                       {-0.5, 0, 0.5}, {0, 1, 0}, {0, 1}, {217 / 255.0, 217 / 255.0, 204 / 255.0, 1} }
            };

            static constexpr std::array grid_axis_x_vertices_ = {
                Vertex{
                       {-0.5, 0, 0}, {0, -1, 0}, {0, 0}, {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}},
                Vertex{
                       {0.5, 0, 0}, {0, -1, 0}, {1, 0}, {217 / 255.0, 217 / 255.0, 204 / 255.0, 1} }
            };

            static constexpr std::array grid_axis_z_vertices_ = {
                Vertex{
                       {0, 0, -0.5}, {0, -1, 0}, {0, 0}, {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}},
                Vertex{
                       {0, 0, 0.5}, {0, -1, 0}, {1, 0}, {217 / 255.0, 217 / 255.0, 204 / 255.0, 1} }
            };

            static constexpr std::array cube_vertices_ = {
                // 前
                Vertex{{-0.5, -0.5, 0.5},
                       {0, 0, 1},
                       {0, 0},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{  {0.5, -0.5, 0.5},
                       {0, 0, 1},
                       {1, 0},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{
                       {0.5, 0.5, 0.5},     {0, 0, 1}, {1, 1}, {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}},
                Vertex{  {-0.5, 0.5, 0.5},
                       {0, 0, 1},
                       {0, 1},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },

                // 后
                Vertex{{-0.5, -0.5, -0.5},
                       {0, 0, -1},
                       {0, 0},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{ {-0.5, 0.5, -0.5},
                       {0, 0, -1},
                       {0, 1},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{  {0.5, 0.5, -0.5},
                       {0, 0, -1},
                       {1, 1},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{ {0.5, -0.5, -0.5},
                       {0, 0, -1},
                       {1, 0},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },

                // 下
                Vertex{ {-0.5, -0.5, 0.5},
                       {0, -1, 0},
                       {0, 0},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{{-0.5, -0.5, -0.5},
                       {0, -1, 0},
                       {1, 0},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{ {0.5, -0.5, -0.5},
                       {0, -1, 0},
                       {1, 1},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{  {0.5, -0.5, 0.5},
                       {0, -1, 0},
                       {0, 1},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },

                // 右
                Vertex{  {0.5, -0.5, 0.5},
                       {1, 0, 0},
                       {0, 0},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{ {0.5, -0.5, -0.5},
                       {1, 0, 0},
                       {1, 0},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{  {0.5, 0.5, -0.5},
                       {1, 0, 0},
                       {1, 1},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{
                       {0.5, 0.5, 0.5},     {1, 0, 0}, {0, 1}, {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}},

                // 上
                Vertex{
                       {0.5, 0.5, 0.5},     {0, 1, 0}, {0, 0}, {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}},
                Vertex{  {0.5, 0.5, -0.5},
                       {0, 1, 0},
                       {1, 0},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{ {-0.5, 0.5, -0.5},
                       {0, 1, 0},
                       {1, 1},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{  {-0.5, 0.5, 0.5},
                       {0, 1, 0},
                       {0, 1},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },

                // 左
                Vertex{  {-0.5, 0.5, 0.5},
                       {-1, 0, 0},
                       {0, 0},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{ {-0.5, 0.5, -0.5},
                       {-1, 0, 0},
                       {1, 0},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{{-0.5, -0.5, -0.5},
                       {-1, 0, 0},
                       {1, 1},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
                Vertex{ {-0.5, -0.5, 0.5},
                       {-1, 0, 0},
                       {0, 1},
                       {217 / 255.0, 217 / 255.0, 204 / 255.0, 1}                                        },
            };

            static constexpr std::array cube_heliostat_vertices_ = {
                // 前
                Vertex{{-0.5, -0.5, 0.5},
                       {0, 0, 1},
                       {0, 0},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{  {0.5, -0.5, 0.5},
                       {0, 0, 1},
                       {1, 0},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{
                       {0.5, 0.5, 0.5},     {0, 0, 1}, {1, 1}, {110.0 / 255, 189.0 / 255, 1, 1}},
                Vertex{  {-0.5, 0.5, 0.5},
                       {0, 0, 1},
                       {0, 1},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },

                // 后
                Vertex{{-0.5, -0.5, -0.5},
                       {0, 0, -1},
                       {0, 0},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{ {-0.5, 0.5, -0.5},
                       {0, 0, -1},
                       {0, 1},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{  {0.5, 0.5, -0.5},
                       {0, 0, -1},
                       {1, 1},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{ {0.5, -0.5, -0.5},
                       {0, 0, -1},
                       {1, 0},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },

                // 下
                Vertex{ {-0.5, -0.5, 0.5},
                       {0, -1, 0},
                       {0, 0},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{{-0.5, -0.5, -0.5},
                       {0, -1, 0},
                       {1, 0},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{ {0.5, -0.5, -0.5},
                       {0, -1, 0},
                       {1, 1},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{  {0.5, -0.5, 0.5},
                       {0, -1, 0},
                       {0, 1},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },

                // 右
                Vertex{  {0.5, -0.5, 0.5},
                       {1, 0, 0},
                       {0, 0},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{ {0.5, -0.5, -0.5},
                       {1, 0, 0},
                       {1, 0},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{  {0.5, 0.5, -0.5},
                       {1, 0, 0},
                       {1, 1},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{
                       {0.5, 0.5, 0.5},     {1, 0, 0}, {0, 1}, {110.0 / 255, 189.0 / 255, 1, 1}},

                // 上
                Vertex{
                       {0.5, 0.5, 0.5},     {0, 1, 0}, {0, 0}, {110.0 / 255, 189.0 / 255, 1, 1}},
                Vertex{  {0.5, 0.5, -0.5},
                       {0, 1, 0},
                       {1, 0},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{ {-0.5, 0.5, -0.5},
                       {0, 1, 0},
                       {1, 1},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{  {-0.5, 0.5, 0.5},
                       {0, 1, 0},
                       {0, 1},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },

                // 左
                Vertex{  {-0.5, 0.5, 0.5},
                       {-1, 0, 0},
                       {0, 0},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{ {-0.5, 0.5, -0.5},
                       {-1, 0, 0},
                       {1, 0},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{{-0.5, -0.5, -0.5},
                       {-1, 0, 0},
                       {1, 1},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
                Vertex{ {-0.5, -0.5, 0.5},
                       {-1, 0, 0},
                       {0, 1},
                       {110.0 / 255, 189.0 / 255, 1, 1}                                        },
            };

            // 前后下右上左
            static constexpr std::array rectangle3d_indices_ = {
                0U,  1U,  2U,  0U,  2U,  3U,  4U,  5U,  6U,  4U,  6U,  7U,
                8U,  9U,  10U, 8U,  10U, 11U, 12U, 13U, 14U, 12U, 14U, 15U,
                16U, 17U, 18U, 16U, 18U, 19U, 20U, 21U, 22U, 20U, 22U, 23U};

            static constexpr std::array axis_vertices_{
                // x轴
                Vertex{         {0, 0, 0}, {0, 0, 0}, {0, 0}, {1, 0, 0, 1}},
                Vertex{         {1, 0, 0}, {0, 0, 0}, {0, 0}, {1, 0, 0, 1}},
                Vertex{         {1, 0, 0}, {0, 0, 0}, {0, 0}, {1, 0, 0, 1}},
                Vertex{   {0.7F, 0.1F, 0}, {0, 0, 0}, {0, 0}, {1, 0, 0, 1}},
                Vertex{         {1, 0, 0}, {0, 0, 0}, {0, 0}, {1, 0, 0, 1}},
                Vertex{  {0.7F, -0.1F, 0}, {0, 0, 0}, {0, 0}, {1, 0, 0, 1}},
                Vertex{   {1.2F, 0.1F, 0}, {0, 0, 0}, {0, 0}, {1, 0, 0, 1}},
                Vertex{  {1.3F, -0.1F, 0}, {0, 0, 0}, {0, 0}, {1, 0, 0, 1}},
                Vertex{  {1.2F, -0.1F, 0}, {0, 0, 0}, {0, 0}, {1, 0, 0, 1}},
                Vertex{   {1.3F, 0.1F, 0}, {0, 0, 0}, {0, 0}, {1, 0, 0, 1}},
                // y轴
                Vertex{         {0, 0, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                Vertex{         {0, 1, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                Vertex{         {0, 1, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                Vertex{   {0.1F, 0.7F, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                Vertex{         {0, 1, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                Vertex{  {-0.1F, 0.7F, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                Vertex{  {0.05F, 1.3F, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                Vertex{      {0, 1.2F, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                Vertex{ {-0.05F, 1.3F, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                Vertex{      {0, 1.2F, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                Vertex{      {0, 1.2F, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                Vertex{      {0, 1.1F, 0}, {0, 0, 0}, {0, 0}, {0, 1, 0, 1}},
                // z轴
                Vertex{         {0, 0, 0}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}},
                Vertex{      {0, 0, 1.0f}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}},
                Vertex{      {0, 0, 1.0f}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}},
                Vertex{  {0.1, 0.0, 0.7f}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}},
                Vertex{      {0, 0, 1.0f}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}},
                Vertex{ {-0.1, 0.0, 0.7f}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}},
                Vertex{  {-0.05, 0, 1.2f}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}},
                Vertex{   {0.05, 0, 1.2f}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}},
                Vertex{   {0.05, 0, 1.2f}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}},
                Vertex{{-0.05, 0.0, 1.1f}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}},
                Vertex{  {-0.05, 0, 1.1f}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}},
                Vertex{ {0.05, 0.0, 1.1f}, {0, 0, 0}, {0, 0}, {0, 0, 1, 1}}
            };

            std::array<Vertex, 2> sunray_vertices_ = {
                Vertex{                       {0, 0, 0},{0, 0, 0}, {0, 0},{1, 231.0 / 255, 110.0 / 255, 1}                   },
                Vertex{{-0.306454, 0.790155, -0.530793},
                       {0, 0, 0},
                       {0, 0},
                       {1, 231.0 / 255, 110.0 / 255, 1}}
            };

            struct OpenGLBufferIndex
            {
                    GLuint vao_ = kUndefined;
                    GLuint vbo_ = kUndefined;
                    GLuint ebo_ = kUndefined;
            };

            std::vector<OpenGLBufferIndex> heliostat_buffer_indices_;
            std::vector<OpenGLBufferIndex> heliostat_pillar_indices_;
            std::vector<OpenGLBufferIndex> reflect_ray_indices_;
            std::vector<OpenGLBufferIndex> sunray_indices_;
            std::vector<OpenGLBufferIndex> grid_axis_x_indices_;
            std::vector<OpenGLBufferIndex> grid_axis_z_indices_;
            OpenGLBufferIndex axis_index_;
            OpenGLBufferIndex receiver_pillar_index_;
            OpenGLBufferIndex receiver_index_;
            OpenGLBufferIndex ground_index_;
            OpenGLBufferIndex skybox_index_;
            OpenGLBufferIndex sun_index_;
            GLuint receiver_texture_index_;
            GLuint skybox_texture_index_;
            std::vector<solar::cuda::inter_op::Float3> all_rectangle_heliostat_normals_;
            std::vector<solar::cuda::inter_op::Float3> all_rectangle_heliostat_centers_;
            std::vector<solar::cuda::inter_op::Float3> all_rectangle_heliostat_sizes_;
            solar::cuda::inter_op::Float3 receiver_center_;
            solar::cuda::inter_op::Float3 receiver_size_; // 长高宽 (x, y, z)
            solar::GeometryType receiver_geometry_type_;
            std::size_t num_heliostats_;
            std::vector<std::array<Vertex, 2>> reflect_vertices_vec_;
            // (pvm_mat, model_mat)
            std::vector<std::pair<glm::mat4, glm::mat4>> heliostat_transform_mats_;
            // (pvm_mat, model_mat)
            std::vector<std::pair<glm::mat4, glm::mat4>> heliostat_pillar_transform_mats_;
            // (pvm_mat, model_mat)
            std::vector<std::pair<glm::mat4, glm::mat4>> sun_ray_transform_mats_;
            // (pvm_mat, model_mat)
            std::vector<std::pair<glm::mat4, glm::mat4>> reflect_ray_transform_mats_;
            // (pvm_mat, model_mat)
            std::vector<std::pair<glm::mat4, glm::mat4>> grid_axis_x_transform_mats_;
            // (pvm_mat, model_mat)
            std::vector<std::pair<glm::mat4, glm::mat4>> grid_axis_z_transform_mats_;

            static auto makeRectangle(const std::vector<solar::cuda::inter_op::Float3>& vertices,
                                      const std::vector<solar::cuda::inter_op::Float3>& normals)
                -> std::vector<Vertex>;
            static auto makeRectangle3D(const std::vector<solar::cuda::inter_op::Float3>& vertices,
                                        const std::vector<solar::cuda::inter_op::Float3>& normals,
                                        const std::vector<solar::cuda::inter_op::Float3>& sizes)
                -> std::vector<Vertex>;
            void deleteAllOpenGLBufferIndices();
            void deleteOpenGLBufferIndicesForSunray();
            void updateSceneInternal();
            void updateSceneForSunrayInternal();

            template <ConstSpanLike VerticesContainer, ConstSpanLike IndicesContainer>
            void loadOpenGLFaceVertices(OpenGLBufferIndex& index,
                                        const VerticesContainer& vertices_container,
                                        const IndicesContainer& indices_container);

            template <ConstSpanLike VerticesContainer>
            void loadOpenGLLineVertices(OpenGLBufferIndex& index,
                                        const VerticesContainer& vertices_container);

            template <ConstSpanLike TextureFilePathContainer>
            void loadCubemapTexture(const TextureFilePathContainer& paths);

            /// @brief 生成正多边形的顶点坐标（单位圆上）
            /// @param num_edges 正多边形的边数
            /// @param buffer 顶点坐标数组(x, z)，y=0
            static constexpr void generatePolygonVertexPositions(int num_edges, float* buffer);

            /// @brief 生成正多边形柱体的侧面法向（单位圆上）
            /// @param num_edges 正多边形的边数
            /// @param buffer 正多边形柱体侧面的法向数组(x, z)，y=0
            static constexpr void generatePolygonFaceNormals(int num_edges, float* buffer);

            /// @brief 生成正多边形柱体的侧面点（单位圆上）
            /// @param num_edges 正多边形的边数
            /// @param positions 正多边形的顶点坐标数组(x, z)
            /// @param normals 正多边形柱体侧面的法向数组(x, z)
            /// @param output 侧面顶点数组（4个点组成1个面，逆时针顺序，从面的左下方的点开始）
            static constexpr void generatePolygonVertices1(int num_edges,
                                                           const float* __restrict positions,
                                                           const float* __restrict normals,
                                                           Vertex* __restrict output);

            /// @brief 生成正多边形柱体的顶面、底面点（单位圆上）
            /// @param num_edges 正多边形的边数
            /// @param positions 正多边形的顶点坐标数组(x, z)
            /// @param output 顶面、底面顶点数组（中心点+正多边形的点，顶面+底面的点）
            static constexpr void
            generatePolygonCeilAndFloorVertices1(int num_edges, const float* __restrict positions,
                                                 Vertex* __restrict output);

            /// @brief 生成正多边形柱体侧面顶点（不含顶面、底面）
            /// @tparam N 正多边形的边数
            template <std::size_t N>
            static consteval auto generatePolygonVertices() -> std::array<Vertex, N * 4>;

            /// @brief 生成正多边形柱体侧面的顶点索引（不含顶面、底面）
            /// @tparam N 正多边形的边数
            template <std::size_t N>
            static consteval auto generatePolygonVertexIndices() -> std::array<GLuint, N * 6>;

            /// @brief 生成正多边形柱体顶点（含顶面、底面）
            /// @tparam N 正多边形的边数
            template <std::size_t N>
            static consteval auto generatePolygonFullVertices() -> std::array<Vertex, N * 6 + 2>;

            /// @brief 生成正多边形柱体的顶点索引（含顶面、底面）
            /// @tparam N 正多边形的边数
            template <std::size_t N>
            static consteval auto generatePolygonFullVertexIndices() -> std::array<GLuint, N * 12>;

            static constexpr void generatePolygonVertexIndicesInternal(int num_edges,
                                                                       GLuint* output);
            static constexpr void generatePolygonFullVertexIndicesInternal(int num_edges,
                                                                           GLuint* output);
            static constexpr void generateSphereVerticesInternal(int segments, Vertex* output);
            static constexpr void generateSphereIndicesInternal(int segments, GLuint* output);

            template <std::size_t N>
            static consteval auto generateSphereVertices() -> std::array<Vertex, (N + 1) * (N + 1)>;

            template <std::size_t N>
            static consteval auto generateSphereIndices() -> std::array<GLuint, 6 * N * N>;

            static auto generatePolygonVertices(int num_edges) -> std::vector<Vertex>;
            static auto generatePolygonFullVertices(int num_edges) -> std::vector<Vertex>;
            static auto generatePolygonVertexIndices(int num_edges) -> std::vector<GLuint>;
            static auto generatePolygonFullVertexIndices(int num_edges) -> std::vector<GLuint>;
            static auto generateSphereVertices(int segments) -> std::vector<Vertex>;
            static auto generateSphereIndices(int segments) -> std::vector<GLuint>;

            template <StringLike Shader1, StringLike Shader2>
            static void initOpenGLShaderProgram(QOpenGLShaderProgram* shader_program,
                                                const Shader1& vertex_shader,
                                                const Shader2& fragment_shader);
    };
} // namespace solar
